use std::any::Any;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use bytes::{Bytes};
use log::info;

// Define a type alias for clarity
type SharedAnyMap = Arc<Mutex<HashMap<&'static str, Box<dyn Any + Send>>>>;

// Create and return a shared, thread-safe HashMap
fn create_shared_map() -> SharedAnyMap {
    let mut map = HashMap::new();
    map.insert("number", Box::new(42) as Box<dyn Any + Send>);
    map.insert("text", Box::new("hello") as Box<dyn Any + Send>);

    Arc::new(Mutex::new(map))
}

// Example of accessing data from the shared map
// fn get_value_from_map(shared_map: &SharedAnyMap, key: &'static str) -> Option<&Box<dyn Any + Send>> {
//     let map = shared_map.lock().unwrap();
//     let value = map.get(key).map(|value| value.clone());
//     value
// }

#[test]
fn main() {
    // Create the shared map
    let shared_map = create_shared_map();

    // Access data from multiple threads
    let thread1_map = Arc::clone(&shared_map);
    let handle1 = std::thread::spawn(move || {
        let map = thread1_map.lock().unwrap();
        if let Some(num) = map.get("number").and_then(|n| n.downcast_ref::<i32>()) {
            info!("Thread 1 found number: {}", num);
        }
    });

    let thread2_map = Arc::clone(&shared_map);
    let handle2 = std::thread::spawn(move || {
        let map = thread2_map.lock().unwrap();
        if let Some(text) = map.get("text").and_then(|t| t.downcast_ref::<&str>()) {
            info!("Thread 2 found text: {}", text);
        }
    });

    handle1.join().unwrap();
    handle2.join().unwrap();

    // Add a new value to the map
    let mut map = shared_map.lock().unwrap();
    map.insert("new_value", Box::new(3.14) as Box<dyn Any + Send>);

    info!("Map now contains {} entries", map.len());
}

#[test]
fn codec_test() {
    let mut map : HashMap<&str, Box<dyn CodecFactory>>= HashMap::new();
    map.insert("json", Box::new(JsonCodec));
    map.insert("bincode", Box::new(BinaryCodec));
}

struct JsonCodec;
struct BinaryCodec;
impl Codec for JsonCodec {
    fn decode<T>(&self) -> T {
        todo!()
    }
}

impl Codec for BinaryCodec {
    fn decode<T>(&self) -> T {
        todo!()
    }
}

trait Codec {
    fn decode<T>(&self)-> T;
}

trait CodecFactory {
    fn create(bytes: Bytes) -> Box<impl Codec> where Self: Sized;
}

impl CodecFactory for JsonCodec {
    fn create(bytes: Bytes) -> Box<impl Codec>
    where
        Self: Sized
    {
        Box::new(JsonCodec)
    }
}

impl CodecFactory for BinaryCodec {
    fn create(bytes: Bytes) -> Box<impl Codec> {
        Box::new(BinaryCodec)
    }
}

#[test]
fn arc_map_test() {
    let mut map = HashMap::new();
    map.insert("s1", 12);
    map.insert("k1", 20);
    let arc_map = Arc::new(map);

    arc_map.iter().for_each(|(k, v)| {
        
    })
}